package pkg;


import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferStrategy;
import 	javax.swing.JOptionPane;
import javax.swing.JFrame;

/**

 * @author Andy
 */

@SuppressWarnings("serial")
public class Game extends JFrame implements KeyListener {

	private GraphicsDevice device;
	private BufferStrategy stratagy;
	private EntityManager manager;
	
	private Canvas drawCanvas;
	private int normalFps = 60;
	private FpsCounter count;
	protected ComponentCollection components;
	protected Player player;
	
	
	public Game()
	{	
		super("BomberBoys");
		setSize(512, 512); //set default size
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	
		
		components = new ComponentCollection();
	
		Map map = new Map();
		map.createMap(10, 10);
		manager = new EntityManager();
		populateMap();
		
		components.addComponent(map);
		components.addComponent(manager);
		count = new FpsCounter();
		components.addComponent(count);
		boolean success = initGraphics(); 
		
		if(!success)
		  JOptionPane.showInputDialog(
				   "Error with hardware acceleration" +
				   "See consoles for details");
		  
	
		this.setIgnoreRepaint(true);
	}
	
	private void populateMap()
	{
		//manager.addEntity(player);
		
		Player play = new Player();
		play.setPosition(150,60);
		manager.addEntity(play);
		play = new Player();
		play.setPosition(100,300);
		manager.addEntity(play);
		play = new Player();
		play.setPosition(160, 150);
		manager.addEntity(play);
	
	}
	
	protected boolean initGraphics()
	{
		setVisible(true);//the frame must be visible to create buffer strategy
		drawCanvas = new Canvas();
		this.add(drawCanvas);
		drawCanvas.addKeyListener(this);
		try {
			GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
			device = ge.getDefaultScreenDevice();
			drawCanvas.createBufferStrategy(2);
			stratagy = drawCanvas.getBufferStrategy();
		
		} 
		catch(Exception ex){
			System.out.println(ex.toString());
		   return false;
		}
		setIgnoreRepaint(true);
		
		
		return true;
	}
	/**
	 * Called once per frame
	 */
	public void render()
	{
		float dt = 1;
		if(count.currentFps != 0)
			dt = normalFps/(float)count.currentFps;
		components.update(dt);
		
			Graphics2D g = (Graphics2D)this.getGraphics();
			try{
				if(stratagy != null)
					g = (Graphics2D)stratagy.getDrawGraphics();
				g.fillRect(0, 0, getWidth(), getHeight());
				g.setColor(Color.BLACK);
				
				components.render(g);
			}
			finally{
				if(g != null)
					g.dispose();
			}

		if(stratagy != null && 
		   !stratagy.contentsLost())
			stratagy.show();
		
		Toolkit.getDefaultToolkit().sync();//i have heard this is something that should be done for linux systems
	}
	
	/**
	 * Tells the window to go full screen if able
	 */
	public boolean setFullScreen(boolean full)
	{
		if(device == null)
			return false; 
		boolean success = false;
		setVisible(false);
		
		dispose(); //we must dispose resources (and recreate) resources to go full screen
		
		if(device.isFullScreenSupported() && full){
			setUndecorated(true); //remove window border
			device.setFullScreenWindow(this);
			this.requestFocus(); //sometimes it could be full screen and not focused
			success = true;
		}
		else {
			setUndecorated(false);
			device.setFullScreenWindow(null);
		}
		setVisible(true);
	
		return success;
	}
	/**
	 * Returns all display modes compatible on current system.
	 */
	public DisplayMode[] getDisplayModes()
	{
		return device.getDisplayModes();
	}
	
	/**
	 * Sets a new display mode thats compatable with system
	 * @param newMode new mode to change to. This mode must be one of the modes from getDisplayModes.
	 * @return returns true if it successfully switched display modes false otherwise.
	 */
	public boolean setDisplayMode(DisplayMode newMode)
	{
		DisplayMode oldDisplay = device.getDisplayMode();
		try{
			if(device.isDisplayChangeSupported())
			   device.setDisplayMode(newMode);
		}
		catch(IllegalArgumentException ex) 
		{
			device.setDisplayMode(oldDisplay);
			return false;
		}
		return true;
	}

	@Override
	public void keyPressed(KeyEvent e) 
	{
		if(e.getKeyCode() == KeyEvent.VK_ESCAPE)
			dispose(); //if this is the last window it sould terminate the program

		
		switch(e.getKeyCode())
		{
			case KeyEvent.VK_A: player.move(Player.Direction.Left); break;
			case KeyEvent.VK_W: player.move(Player.Direction.Up); break;
			case KeyEvent.VK_D: player.move(Player.Direction.Right); break;
			case KeyEvent.VK_S: player.move(Player.Direction.Down); break;
		}
		//e.consume();
	}

	@Override
	public void keyReleased(KeyEvent e) 
	{
		switch(e.getKeyCode())
		{
			case KeyEvent.VK_A: 
			case KeyEvent.VK_W:
			case KeyEvent.VK_D:
			case KeyEvent.VK_S:
				player.stop();
			break;
		}
	}

	@Override
	public void keyTyped(KeyEvent e) {}
	
	public static void main(String[] args)
	{
		Game game = new Game();
		game.setFullScreen(false);
		game.setDisplayMode(game.getDisplayModes()[0]);
		while(game.isVisible())
			game.render();	
	}
}
